#include "CD3D9Sprite.h"
#include "Render\CTexture.h"

#include "D3D9\CD3D9RenderSystem.h"

namespace Nervus {
	namespace Render {
		//----------------------------------------------------------------------------------
		D3D9Sprite::D3D9Sprite(void* renderer, D3DXVECTOR2 pos, Texture* tex)
			: mTexture(NULL), mVertexBuffer(NULL) 
		{
			mRenderSystem = static_cast<D3D9RenderSystem*>(renderer);
			mTextureFile = tex;
			mPosX = pos.x;
			mPosY = pos.y;
			mWidth = tex->mImageWidth;
			mHeight = tex->mImageHeight;
		}
		//----------------------------------------------------------------------------------
		D3D9Sprite::~D3D9Sprite(){

		}
		//----------------------------------------------------------------------------------
		bool D3D9Sprite::loadSprite(){

			//mRenderSystem->loadTexture(mTextureFile, mTexture);
			if (!mTextureFile->loadImageFromFile()){
				return false;
			}


			if (FAILED(mRenderSystem->mVideoCard->CreateTexture(mWidth, mHeight, 1, 0, D3DFMT_A8R8G8B8,
				D3DPOOL_MANAGED, &mTexture, NULL)))
			{
				return false;
			}


			//DirectX reads texture data from the end
			//So image data needs to be reversed
			u32 imageSize = mHeight * mWidth * 4;
			u8* revData = new u8[imageSize];

			for (i32 c = mHeight - 1; c >= 0; c--){	//Processes rows
				for (u32 r = 0; r < mWidth; r++){		//Processes one row
					for (u32 b = 0; b < 4; b++){					//Processes pixel (4-byte chunk)
						revData[c*mWidth * 4 + r * 4 + b] =
							mTextureFile->mImageData[(mHeight - c - 1)*mWidth * 4 + r * 4 + (3 - b)];
					}
				}
			}


			D3DLOCKED_RECT rect;
			mTexture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
			u8* pbyDst = (u8*)(rect.pBits);
			memcpy(pbyDst, revData, mHeight * mWidth * 4);
			mTexture->UnlockRect(0);
			delete[] revData;

			//####################################################################################################
			//####################################################################################################

			SpriteVertex sprt[4];
			sprt[0] = { (f32)mPosX,				(f32)mPosY,				0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f };	//A
			sprt[1] = { (f32)mPosX + mWidth,	(f32)mPosY,				0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f };	//B
			sprt[2] = { (f32)mPosX,				(f32)mPosY + mHeight,	0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f };	//C
			sprt[3] = { (f32)mPosX + mWidth,	(f32)mPosY + mHeight,	0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f };	//D

			mRenderSystem->mVideoCard->CreateVertexBuffer(4 * sizeof(SpriteVertex), 0, VERTEX_FORMAT_2D, D3DPOOL_MANAGED,
				&mVertexBuffer, NULL);

			void* pVertices;
			mVertexBuffer->Lock(0, 0, (void**)&pVertices, 0);
			memcpy(pVertices, &(sprt[0]), 4 * sizeof(SpriteVertex));
			mVertexBuffer->Unlock();


			return true;
		}
		//----------------------------------------------------------------------------------
		void D3D9Sprite::renderSprite(){
			mRenderSystem->mVideoCard->SetTexture(0, mTexture);
			
			mRenderSystem->mVideoCard->SetFVF(VERTEX_FORMAT_2D);
			mRenderSystem->mVideoCard->SetStreamSource(0, mVertexBuffer, 0, sizeof(SpriteVertex));
			mRenderSystem->mVideoCard->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		}
		//----------------------------------------------------------------------------------
		//----------------------------------------------------------------------------------
		//----------------------------------------------------------------------------------
	}
}